package com.jintian.smart.kernel.common.expr.op.define;

import com.jintian.smart.kernel.core.expr.IllegalExpressionException;
import com.jintian.smart.kernel.common.expr.datameta.BaseDataMeta;
import com.jintian.smart.kernel.common.expr.datameta.Constant;
import com.jintian.smart.kernel.common.expr.op.IOperatorExecution;
import com.jintian.smart.kernel.common.expr.op.Operator;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;

public abstract class Op_Base implements IOperatorExecution {
	private final Operator operator;

	public Op_Base(Operator operator) {
		this.operator = operator;
	}

	@Override
	public Operator getOperator() {
		return this.operator;
	}

	public Constant execute(Constant[] args) {
		throw new UnsupportedOperationException("操作符\"" + this.getOperator().getToken() + "不支持该方法");
	}

	public Object[] getParameterValues(Constant[] args) {
		Object[] params = new Object[args.length];
		for (int argIndex = args.length - 1, paramIndex = 0; argIndex >= 0; argIndex--, paramIndex++) {
			params[paramIndex] = args[argIndex].toJavaObject();
			if (params[paramIndex] == null && !this.getOperator().isNullable(paramIndex)) {
				throw new NullPointerException(
						"操作符\"" + this.getOperator().getToken() + "\"第" + (paramIndex + 1) + "个参数为空");
			}
		}
		return params;
	}

	public Constant verify(int opPositin, BaseDataMeta[] args) throws IllegalExpressionException {
		throw new UnsupportedOperationException("操作符\"" + this.getOperator().getToken() + "不支持该方法");
	}

	public boolean isNumberClass(BaseDataMeta parameter) {
		Class<?> cls = parameter.mapTypeToJavaClass();
		if (cls == null) {
			return false;
		}
		return Number.class.isAssignableFrom(cls) || Object.class.equals(cls); // 有可能是函数返回值Object
	}

	public Constant numberVerifyResult(int opPositin, BaseDataMeta[] args) {
		Set<Class<?>> list = new HashSet<>();
		int index = 1;
		for (BaseDataMeta m : args) {
			if (!isNumberClass(m)) {
				throw new IllegalExpressionException(
						"操作符\"" + this.getOperator().getToken() + "\"第" + index + "个参数类型错误",
						this.getOperator().getToken(), opPositin);
			}
			list.add(m.mapTypeToJavaClass());
			index++;
		}

		if (list.contains(Object.class)) {
			return new Constant(BaseDataMeta.DataType.DATATYPE_BIGDECIMAL, BigDecimal.valueOf(0d));
		} else if (list.contains(BigDecimal.class)) {
			return new Constant(BaseDataMeta.DataType.DATATYPE_BIGDECIMAL, BigDecimal.valueOf(0d));
		} else if (list.contains(Double.class)) {
			return new Constant(BaseDataMeta.DataType.DATATYPE_DOUBLE, Double.valueOf(0d));
		} else if (list.contains(Float.class)) {
			return new Constant(BaseDataMeta.DataType.DATATYPE_FLOAT, Float.valueOf(0f));
		} else if (list.contains(Long.class)) {
			return new Constant(BaseDataMeta.DataType.DATATYPE_LONG, Long.valueOf(0l));
		} else if (list.contains(Integer.class)) {
			return new Constant(BaseDataMeta.DataType.DATATYPE_INT, Integer.valueOf(0));
		} else {
			throw new IllegalExpressionException("操作符\"" + this.getOperator() + "\"参数类型错误",
					this.getOperator().getToken(), opPositin);
		}
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public int compare(Object o1, Object o2, Comparator<Object> comparator) {
		if (o1 == o2 || o1 == null && o2 == null) {
			return 0;
		}
		if (o1 == null || o2 == null)
			throw new IllegalArgumentException("不能比较空值");
		if (comparator != null) {
			return comparator.compare(o1, o2);
		}

		if (o1 instanceof Number && o2 instanceof Number) {
			return new NumberComparator().compare((Number) o1, (Number) o2);
		}

		if (o1 instanceof Comparable) {
			return ((Comparable) o1).compareTo(o2);
		} else if (o2 instanceof Comparable) {
			return ((Comparable) o2).compareTo(o1);
		} else {
			throw new IllegalArgumentException("不支持的类型比较");
		}
	}

}
